package com.starlight.flower_server.domain.service.impl;

import com.baomidou.mybatisplus.core.metadata.IPage;
import com.starlight.flower_server.controller.exception.BadRequestException;
import com.starlight.flower_server.controller.exception.NotFoundException;
import com.starlight.flower_server.domain.TotalData;
import com.starlight.flower_server.domain.order.cqrs.OrderPageQuery;
import com.starlight.flower_server.domain.order.data.OrderData;
import com.starlight.flower_server.infrastructure.Status;
import com.starlight.flower_server.infrastructure.entity.FlowerUser;
import com.starlight.flower_server.infrastructure.entity.Item;
import com.starlight.flower_server.infrastructure.entity.Order;
import com.starlight.flower_server.infrastructure.repository.FlowerUserRepository;
import com.starlight.flower_server.infrastructure.repository.ItemRepository;
import com.starlight.flower_server.infrastructure.repository.OrderRepository;
import com.starlight.flower_server.domain.service.OrderService;
import com.starlight.flower_server.infrastructure.util.CurrentUserInfoUtils;
import jakarta.annotation.Resource;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.util.Date;
import java.util.List;
import java.util.Map;

/**
 * @Author yfy2001
 * @date 2023/4/5 15:07
 */
@Service
public class OrderServiceImpl implements OrderService {

    @Resource
    private FlowerUserRepository flowerUserRepository;
    
    @Resource
    private OrderRepository orderRepository;

    @Resource
    ItemRepository itemRepository;

    @Override
    public Order queryOrderDetailById(Long id) {
        Order order=orderRepository.queryDetail(id);
        if (order==null){
            throw new NotFoundException(Status.RECORD_NOT_FOUND.getMessage(),Status.RECORD_NOT_FOUND);
        }
        return order;
    }

    @Override
    public Integer logicDeleteOrderById(Long id) {
        Order order=orderRepository.queryDetail(id);
        if (order.getIsPaid().equals(0)||order.getIsCompleted().equals(0)){
            Item item=itemRepository.queryDetail(order.getItemId());
            //删除未支付或未完成订单时返还库存
            Integer stock=item.getStock();
            stock=stock+order.getNumber();
            item.setStock(stock);
            itemRepository.autoModifyStock(item);
        }
        Integer i=orderRepository.logicDelete(id);
        if (i.equals(0)){
            throw new NotFoundException(Status.RECORD_NOT_FOUND.getMessage(),Status.RECORD_NOT_FOUND);
        }
        return i;
    }

    @Override
    @Transactional
    public Integer insertOrder(Order order) {
        if(order.getNumber().equals(0)){
            throw new BadRequestException(Status.INVALID_ORDER_NUMBER.getMessage(),Status.INVALID_ORDER_NUMBER);
        }
        Item item=itemRepository.queryDetail(order.getItemId());
        if(order.getNumber()>item.getStock()){
            throw new BadRequestException(Status.INVALID_ORDER_STOCK.getMessage(),Status.INVALID_ORDER_STOCK);
        }
        //创建订单减去商品库存
        Integer stock=item.getStock();
        stock=stock-order.getNumber();
        item.setStock(stock);
        itemRepository.autoModifyStock(item);
        //设置订单信息
        order.setItemId(item.getId());
        Long userId= Long.valueOf(CurrentUserInfoUtils.getUserId());
        FlowerUser flowerUser= flowerUserRepository.queryDetail(userId);
        if(order.getAddress()==null&&flowerUser.getAddress()==null){
            //如果地址为空且用户默认地址也为空：创建失败
            throw new BadRequestException(Status.INVALID_ORDER_ADDRESS.getMessage(),Status.INVALID_ORDER_ADDRESS);
        } else if (order.getAddress()!=null&&flowerUser.getAddress()==null) {
            //如果地址不为空但用户默认地址为空：使用当前地址并修改用户默认地址
            flowerUser.setAddress(order.getAddress());
            flowerUserRepository.modify(flowerUser);
        } else if (order.getAddress() == null) {
            order.setAddress(flowerUser.getAddress());
        }
        //获取折扣
        BigDecimal discount = order.getDiscount();
        //折扣不在0.5-1范围内
        if (discount.doubleValue() > 1 || discount.doubleValue() < 0.5) {
            throw new BadRequestException(Status.INVALID_ORDER_DISCOUNT.getMessage(),Status.INVALID_ORDER_DISCOUNT);
        }
        //计算订单总价
        BigDecimal price=item.getPrice();
        BigDecimal itemNumber=new BigDecimal(order.getNumber().toString());
        BigDecimal total=price.multiply(itemNumber).multiply(discount);
        order.setTotalCharge(total);
        return orderRepository.insert(order);
    }

    @Override
    public Integer modifyOrder(Order order) {
        Order oldOrder = orderRepository.queryDetail(order.getId());
        Long itemId=oldOrder.getItemId();
        if (!itemId.equals(order.getItemId())) {
            throw new BadRequestException("修改订单失败：无法将订单修改为其他商品，请删除订单后重新下单其他商品",Status.EXCEPTION);
        }
        //老需求量
        Integer oldRequirement=oldOrder.getNumber();
        //新需求量
        Integer requirement=order.getNumber();
        //订单对应商品
        Item item=itemRepository.queryDetail(itemId);
        //当前库存
        Integer nowStock=item.getStock();
        if (order.getNumber()!=null){
            if (requirement.equals(0)) {
                throw new BadRequestException(Status.INVALID_ORDER_NUMBER.getMessage(),Status.INVALID_ORDER_NUMBER);
            }
            item = itemRepository.queryDetail(order.getId());
            //最大供应量=老订单预定数目+商品库存
            int totalNumber = oldOrder.getNumber() + nowStock;
            if (requirement > totalNumber) {
                throw new BadRequestException(Status.INVALID_ORDER_STOCK.getMessage(),Status.INVALID_ORDER_STOCK);
            }
        }
        //
        BigDecimal oldDiscount=oldOrder.getDiscount();
        //获取折扣
        BigDecimal discount = order.getDiscount();
        //折扣不在0.5-1范围内
        if (discount.doubleValue() > 1 || discount.doubleValue() < 0.5) {
            throw new BadRequestException(Status.INVALID_ORDER_DISCOUNT.getMessage(),Status.INVALID_ORDER_DISCOUNT);
        }
        //折扣或数量更改时重新计算总价
        if (!(oldRequirement.equals(requirement)&&oldDiscount.equals(discount))){
            //计算订单总价
            BigDecimal price=item.getPrice();
            assert order.getNumber() != null;
            BigDecimal itemNumber=new BigDecimal(order.getNumber().toString());
            BigDecimal total=price.multiply(itemNumber).multiply(discount);
            order.setTotalCharge(total);
        }
        Integer i = orderRepository.modify(order);
        if (!i.equals(0)&&order.getNumber()!=null) {
            //重新计算商品库存
            item.setStock(nowStock + oldOrder.getNumber() - requirement);
            itemRepository.autoModifyStock(item);
        } else {
            throw new BadRequestException("修改订单失败!",Status.ERROR);
        }
        return i;
    }

    @Override
    public IPage<OrderData> queryOrderList(OrderPageQuery query) {
        IPage<Order> page=orderRepository.queryPage(query);
        IPage<OrderData> data=page.convert(order -> {
            OrderData orderData=new OrderData();
            BeanUtils.copyProperties(order,orderData);
            return orderData;
        });
        List<OrderData> orderDataList=data.getRecords();
        setItemAndFlowerUserInfo(orderDataList);
        data.setRecords(orderDataList);
        return data;
    }

    /**
     * 查询用户所有订单
     * @param id
     * @return
     */
    @Override
    public List<OrderData> queryFlowerUserOrderByFlowerUserId(Long id) {
        List<Order> orderList=orderRepository.queryListByFlowerUserId(id);
        return orderList
                .stream().map(order -> {
                    OrderData orderData=new OrderData();
                    BeanUtils.copyProperties(order,orderData);
                    return orderData;
                }).toList();
    }

    @Override
    public List<OrderData> queryOrderListByIdList(List<Long> orderIdList) {
        List<Order> orderList=orderRepository.queryListByIdList(orderIdList);
        return orderList
                .stream().map(order -> {
                    OrderData orderData=new OrderData();
                    BeanUtils.copyProperties(order,orderData);
                    return orderData;
                }).toList();
    }

    @Override
    public TotalData<OrderData> queryAllOrderData() {
        TotalData<OrderData> data=new TotalData<>();
        List<Order> orderList=orderRepository.queryAll();
        List<OrderData> orderDataList=orderList
                .stream().map(order -> {
                    OrderData orderData=new OrderData();
                    BeanUtils.copyProperties(order,orderData);
                    return orderData;
                }).toList();
        setItemAndFlowerUserInfo(orderDataList);
        Long total=(long) orderDataList.size();
        data.setTable("Order");
        data.setStatTime(new Date());
        data.setTotal(total);
        data.setRecords(orderDataList);
        return data;
    }

    private void setItemAndFlowerUserInfo(List<OrderData> orderDataList) {
        //获取订单对应商品信息
        List<Long> itemIdList=orderDataList.stream().map(OrderData::getItemId).toList();
        Map<Long,Item> itemMap=itemRepository.queryMap(itemIdList);
        //获取订单对应用户信息
        List<Long> flowerUserIdList=orderDataList.stream().map(OrderData::getFlowerUserId).toList();
        Map<Long,FlowerUser> flowerUserMap=flowerUserRepository.queryMap(flowerUserIdList);
        for (OrderData o:orderDataList){
            //设置商品信息
            o.setItemName(itemMap.get(o.getItemId()).getName());
            o.setItemPrice(itemMap.get(o.getItemId()).getPrice());
            //设置用户信息
            o.setFlowerUserNickname(flowerUserMap.get(o.getFlowerUserId()).getNickname());
        }
    }

    @Override
    public TotalData<OrderData> queryOrderTotalCount() {
        TotalData<OrderData> data=new TotalData<>();
        Long total= orderRepository.queryTotalCount();
        data.setTable("Order");
        data.setStatTime(new Date());
        data.setTotal(total);
        return data;
    }

    @Override
    public Integer paySelectedOrder(Long orderId) {
        Order order=orderRepository.queryDetail(orderId);
        order.setIsPaid(1);
        return orderRepository.modify(order);
    }

    @Override
    public Integer completeSelectedOrder(Long orderId) {
        Order order=orderRepository.queryDetail(orderId);
        order.setIsCompleted(1);
        return orderRepository.modify(order);
    }
}
